﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using NetDon.OA.Business;
using NetDon.OA.Data.EntityClasses;
using NetDon.OA.Interface;
using NetDon.OA.Interface.CRM;
using NetDon.OA.Portal.Common;
using NetDon.Utilities;
using NetDon.WebControls;

namespace NetDon.OA.Portal
{
    #region Attributes

    [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
    public class PageTabberAttribute : Attribute
    {
        public string Title { get; set; }
        public string NavigateUrl { get; set; }
        public int Index { get; set; }
        public Type Type { get; set; }
    }

    [Serializable]
    public class PageTab
    {
        public string Title { get; set; }
        public string NavigateUrl { get; set; }
        public int Index { get; set; }
        public Type Type { get; set; }
    }

    [Serializable]
    public class PageTabCollection : Collection<PageTab>
    {
        public PageTabCollection(IList<PageTab> list)
            : base(list)
        {
        }

        public PageTabCollection()
        {
        }

        public PageTab this[string tabName]
        {
            get
            {
                foreach (PageTab pageTab in this)
                {
                    if (string.Compare(pageTab.Title, tabName) == 0)
                    {
                        return pageTab;
                    }
                }
                return null;
            }
        }
    }

    public class FunctionAttribute : Attribute
    {
        public FunctionAttribute(string functionId)
        {
            FunctionId = functionId;
        }

        public string FunctionId { get; private set; }
    }

    [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
    public class CommandAttribute : Attribute
    {
        private bool _causesValidation = true;
        private string _validationGroup;
        private string _displayText;

        public CommandAttribute(string commandName, string imageUrl)
        {
            CommandName = commandName;
            ImageUrl = imageUrl;
        }

        public string DisplayText
        {
            get
            {
                if (string.IsNullOrEmpty(_displayText))
                {
                    return CommandName;
                }
                return _displayText;
            }
            set { _displayText = value; }
        }

        public string CommandName { get; set; }

        public string CommandArgument { get; set; }

        public bool CausesValidation
        {
            get { return _causesValidation; }
            set { _causesValidation = value; }
        }

        public string ValidationGroup
        {
            get { return _validationGroup ?? string.Empty; }
            set { _validationGroup = value; }
        }

        public string ImageUrl { get; set; }

        public int Order { get; set; }
    }

    [Serializable]
    public class CommandButton
    {
        private bool _visible = true;

        public CommandButton(string commandName, string commandArgument, string imageUrl, string displayText, bool causesValidation, string validationGroup)
        {
            DisplayText = displayText;
            ImageUrl = imageUrl;
            CommandArgument = commandArgument;
            CommandName = commandName;
            CausesValidation = causesValidation;
            ValidationGroup = validationGroup;
        }

        public string CommandName { get; private set; }

        public string CommandArgument { get; private set; }

        public string ImageUrl { get; private set; }

        public string DisplayText { get; private set; }

        public bool CausesValidation { get; private set; }

        public string ValidationGroup { get; private set; }

        public bool Visible
        {
            get { return _visible; }
            set { _visible = value; }
        }
    }

    [Serializable]
    public class CommandButtonCollection : Collection<CommandButton>
    {
        public CommandButtonCollection(IList<CommandButton> list)
            : base(list)
        {
        }

        public CommandButtonCollection()
        {
        }

        public CommandButton this[string commandName]
        {
            get
            {
                foreach (CommandButton button in this)
                {
                    if (string.Compare(button.CommandName, commandName) == 0)
                    {
                        return button;
                    }
                }
                return null;
            }
        }
    }

    #endregion

    public class PageBase : NetDonPage
    {
        #region Constructors

        /// <summary>
        /// Initializes a new instance of the <see cref="PageBase"/> class.
        /// </summary>
        protected PageBase()
        {

        }
        /// <summary>
        /// Initializes a new instance of the <see cref="PageBase"/> class.
        /// </summary>
        /// <param name="enableClientState">if set to <c>true</c> [enable client state].</param>
        protected PageBase(bool enableClientState)
            : base(enableClientState)
        {

        }
        #endregion

        #region Fields

        private const string PostCommandArgumentID = "__COMMANDARGUMENT";
        private const string PostCommandNameID = "__COMMANDNAME";

        private static MethodInfo RegisterWebFormsScriptMethod;

        private static readonly object RegisterWebFormsScriptLock = new object();

        private static readonly object EventCommand = new object();
        private static readonly string[] IgnorePaths = new[] { "~/Default.aspx" };

        public static OApplicationContext CurrentApplicationContext
        {
            get
            {
                return ServiceContainer.GetService<ApplicationContext>() as OApplicationContext;
            }
        }

        public virtual string[] NavigationPath
        {
            get
            {
                if (ViewState["NavigationPath"] == null)
                {
                    var attribute =
                        (NavigationAttribute)Attribute.GetCustomAttribute(GetType(), typeof(NavigationAttribute));
                    ViewState["NavigationPath"] = attribute == null ? new string[0] : attribute.Path;
                }
                return (string[])ViewState["NavigationPath"];
            }
        }

        public static string[] GetNavigationPath(string functionId)
        {
            var service = ServiceContainer.GetService<ISecurityService>();
            var stack = new Stack();
            var context = ServiceContainer.GetService<ApplicationContext>();
            if (GetNavigationPath(service.GetPermitModules(context.UserId), stack, functionId))
            {
                var array = (string[])new ArrayList(stack).ToArray(typeof(string));
                Array.Reverse(array);
                return array;
            }
            return null;
        }

        private static bool GetNavigationPath(IEnumerable<Interface.Module> modules, Stack stack, string functionId)
        {
            foreach (var module in modules)
            {
                stack.Push(module.Name);
                if (string.Compare(module.ModuleID, functionId, true) == 0)
                {
                    return true;
                }
                if (GetNavigationPath(module.Functions, stack, functionId))
                {
                    return true;
                }
                stack.Pop();
            }
            return false;
        }

        private static bool GetNavigationPath(IEnumerable<Function> functions, Stack stack, string functionId)
        {
            foreach (var function in functions)
            {
                stack.Push(function.Name);
                if (string.Compare(function.FunctionID, functionId, true) == 0)
                {
                    return true;
                }
                if (GetNavigationPath(function.Functions, stack, functionId))
                {
                    return true;
                }
                if (GetNavigationPath(function.Operations, stack, functionId))
                {
                    return true;
                }
                stack.Pop();
            }
            return false;
        }

        private static bool GetNavigationPath(IEnumerable<Operation> operations, Stack stack, string functionId)
        {
            foreach (var operation in operations)
            {
                stack.Push(operation.Name);
                if (string.Compare(operation.OperationID, functionId, true) == 0)
                {
                    return true;
                }
                stack.Pop();
            }
            return false;
        }

        #endregion

        #region Permission

        /// <summary>
        /// 获取当前功能页面的标志。
        /// </summary>
        protected virtual string FunctionId
        {
            get
            {
                var attr = this.GetAttribute<FunctionAttribute>();
                var context = (OApplicationContext)ServiceContainer.GetService<ApplicationContext>();
                return attr != null ? attr.FunctionId : context.AccessingFunction;
            }
        }

        /// <summary>
        /// Verifies the login user.
        /// </summary>
        private void VerifyLoginUser()
        {
            var context = ServiceContainer.GetService<ApplicationContext>();
            if (context.UserId != Guid.Empty)
            {
                return;
            }
            if (User.Identity.IsAuthenticated)
            {
                if (context.UserId != Guid.Empty)
                {
                    return;
                }
                var service = ServiceContainer.GetService<ISecurityService>();
                if (service.LoginDirect(User.Identity.Name))
                {
                    return;
                }
            }
            if (!Page.IsCallback)
            {
                FormsAuthentication.RedirectToLoginPage();
                Response.End();
            }
        }

        /// <summary>
        /// Raises the <see cref="E:System.Web.UI.Page.PreInit"/> event at the beginning of page initialization.
        /// </summary>
        /// <param name="e">An <see cref="T:System.EventArgs"/> that contains the event data.</param>
        protected override void OnPreInit(EventArgs e)
        {
            VerifyLoginUser();
            bool ignore = false;
            foreach (string path in IgnorePaths)
            {
                if (string.Compare(Request.AppRelativeCurrentExecutionFilePath, path, true) == 0)
                {
                    ignore = true;
                    break;
                }
            }
            if (!ignore)
            {
                string function = FunctionId;
                var context = (OApplicationContext)ServiceContainer.GetService<ApplicationContext>();
                if (!CheckPermission(function))
                {
                    var logService = ServiceContainer.GetService<ILogService>();
                    logService.Log(new LoggingEvent
                    {
                        ApplicationId = context.ApplicationId,
                        Category = EventCategories.Security,
                        Level = LogLevel.FailureAudit,
                        Source = "安全",
                        UserName = context.UserName,
                        Message =
                            string.Format(
                            "Authentication failed: The function '{0}' was forbidden to user '{1}'.",
                            FunctionId, new UserEntity(context.UserId).UserName)
                    });
                    throw new HttpException(403, string.Format("Path '{0}' is forbidden", Request.Path));
                }
                context.AccessingFunction = function;
            }
            base.OnPreInit(e);
        }

        /// <summary>
        /// 验证当前登录的用户对某个功能或操作是否有权限。
        /// </summary>
        /// <param name="function">功能的ID</param>
        /// <returns></returns>
        protected Boolean CheckPermission(string function)
        {
            var service = ServiceContainer.GetService<ISecurityService>();
            var context = ServiceContainer.GetService<ApplicationContext>();
            return service.ValidatePermission(context.UserId, function);
        }
      
        public bool IsManager()
        {
            if(!CurrentApplicationContext.PositionId.HasValue) return false;
            var dictonaryService = ServiceContainer.GetService<IDictionaryService>();
            var positionLevelName = dictonaryService.GetDataName(new PostEntity(CurrentApplicationContext.PositionId.Value).PostLevel);

            var postionLevelArray = WebConfig.PositionLevels.Split(new char[] { ';' });
            return postionLevelArray.Contains(positionLevelName);

        }
  
        public bool IsSuperRoles()
        {
            if(!CurrentApplicationContext.RoleId.HasValue) return false;

           
            var positionLevelName = new RoleEntity(CurrentApplicationContext.RoleId.Value).RoleName;

            var postionLevelArray = WebConfig.SuperRoles.Split(new char[] { ';' });
            return postionLevelArray.Contains(positionLevelName);

        }

        
        #endregion

        #region PageCommand

        private void EnsureRegisterWebFormsScriptMethod()
        {
            if (RegisterWebFormsScriptMethod == null)
            {
                lock (RegisterWebFormsScriptLock)
                {
                    if (RegisterWebFormsScriptMethod == null)
                    {
                        RegisterWebFormsScriptMethod = typeof(Page).GetMethod("RegisterWebFormsScript",
                                                                               BindingFlags.NonPublic |
                                                                               BindingFlags.Instance, null,
                                                                               Type.EmptyTypes, null);
                    }
                }
            }
        }

        private void RegisterWebFormsScript()
        {
            EnsureRegisterWebFormsScriptMethod();
            RegisterWebFormsScriptMethod.Invoke(this, new object[0]);
        }

        public virtual PageTabCollection PageTabers
        {
            get
            {
                if (ViewState["PageTabers"] == null)
                {
                    Attribute[] attributes = Attribute.GetCustomAttributes(GetType(), typeof(PageTabberAttribute));
                    var commands = new PageTabberAttribute[attributes.Length];
                    attributes.CopyTo(commands, 0);
                    Array.Sort(commands, (x, y) => Comparer<int>.Default.Compare(x.Index, y.Index));
                    ViewState["PageTabers"] =
                        new PageTabCollection(
                            commands.Select(
                                attr =>
                                new PageTab()
                                    {
                                        Index = attr.Index,
                                        NavigateUrl = attr.NavigateUrl,
                                        Title = attr.Title,
                                        Type = attr.Type

                                    }).ToList());
                }

                return (PageTabCollection)ViewState["PageTabers"];
            }
        }

        public CommandButtonCollection CommandButtons
        {
            get
            {
                if (ViewState["CommandButtons"] == null)
                {
                    Attribute[] attributes = Attribute.GetCustomAttributes(GetType(), typeof(CommandAttribute));
                    var commands = new CommandAttribute[attributes.Length];
                    attributes.CopyTo(commands, 0);
                    Array.Sort(commands, (x, y) => Comparer<int>.Default.Compare(x.Order, y.Order));
                    ViewState["CommandButtons"] =
                        new CommandButtonCollection(
                            commands.Select(
                                attr =>
                                new CommandButton(attr.CommandName, attr.CommandArgument, attr.ImageUrl,
                                                  attr.DisplayText, attr.CausesValidation, attr.ValidationGroup)).ToList());
                }
                return (CommandButtonCollection)ViewState["CommandButtons"];
            }
        }

        protected override void OnPreRender(EventArgs e)
        {
            if (!MiscUtilities.IsNullOrEmpty(CommandButtons))
            {
                RegisterWebFormsScript();
                ClientScript.RegisterHiddenField(PostCommandNameID, string.Empty);
                ClientScript.RegisterHiddenField(PostCommandArgumentID, string.Empty);

                ScriptStartup(string.Format("document.getElementById('{0}').value='';", PostCommandNameID));
                ScriptStartup(string.Format("document.getElementById('{0}').value='';", PostCommandArgumentID));

                var listCommandNames = new List<string>();
                foreach (var commandButton in CommandButtons)
                {
                    listCommandNames.Add(commandButton.CommandName);
                    ScriptStartup(string.Format("__showCommandButton('{0}',{1});", commandButton.CommandName, commandButton.Visible.ToString().ToLower()));
                }
                if (listCommandNames.Count > 0)
                {
                    ScriptStartup(string.Format("__commandNames=['{0}']", string.Join("','", listCommandNames.ToArray())));
                }
            }
            base.OnPreRender(e);
        }

        protected override void OnLoadComplete(EventArgs e)
        {
            string commandName = Request.Form[PostCommandNameID];
            if (!string.IsNullOrEmpty(commandName))
            {
                string commandArgument = Request.Form[PostCommandArgumentID];
                OnCommand(new CommandEventArgs(commandName, commandArgument));
            }
            base.OnLoadComplete(e);
        }

        protected virtual void OnCommand(CommandEventArgs args)
        {
            var handler = (CommandEventHandler)Events[EventCommand];
            if (handler != null)
            {
                handler(this, args);
            }
        }

        [Category("Action")]
        public event CommandEventHandler Command
        {
            add { Events.AddHandler(EventCommand, value); }
            remove { Events.RemoveHandler(EventCommand, value); }
        }

        #endregion

        protected string GetCustomerName(object id)
        {
            if (MiscUtilities.IsNullOrEmpty(id)) return string.Empty;
            var service = ServiceContainer.GetService<ICustomerInfoService>();
            var customer = service.GetCustomerInfo(id.ToString().ToGuid());
            return customer == null ? string.Empty : customer.CustomerName;

        }
        public string GetDictionaryItemName(object id)
        {
            if (MiscUtilities.IsNullOrEmpty(id)) return string.Empty;
            var service = ServiceContainer.GetService<IDictionaryService>();
            var item = service.GetDataItem(id.ToString().ToGuid());

            return item == null ? string.Empty : item.Name;

        }
        protected string GetCityName(object issuingOrderId)
        {
            if (MiscUtilities.IsNullOrEmpty(issuingOrderId)) return string.Empty;
            var orderService = ServiceContainer.GetService<IIssuingOrderService>();
            var issuingOrderDeliveryData = orderService.GetIssuingOrderDeliveryByOrderId(issuingOrderId.ToString().ToGuid());
            if (!issuingOrderDeliveryData.Any()) return string.Empty;
            return issuingOrderDeliveryData.Select(a => a.DeliveryCity).Distinct().Select(a => new CityEntity(a).Name).Aggregate((a, b) => a + "," + b);

        }
        protected string GetSingleCityName(object id)
        {
            var cityName = new StringBuilder();
            var service = ServiceContainer.GetService<ILocationService>();
            if (!MiscUtilities.IsNullOrEmpty(id))
            {
                cityName.Append(service.GetCity(id.ToString()).Name).Append(" ");
            }

            return cityName.ToString();


        }

        protected void DateValidator_ServerValidate(object sender, ServerValidateEventArgs e)
        {
            DateTime value;
            e.IsValid = DateTime.TryParse(e.Value, out value);
        }
    }

    public class NavigationPageBase : PageBase
    {

        protected int CurrentIndex
        {
            set { ViewState["CurrentIndex"] = value; }
            get
            {
                if (ViewState["CurrentIndex"] != null)
                    return int.Parse(ViewState["CurrentIndex"].ToString());
                return 0;
            }
        }


        protected virtual IList<Guid> Ids { get; set; }

        protected OrderStatus OrderStatus
        {
            set { ViewState["OrderStatus"] = value; }
            get
            {
                if (ViewState["OrderStatus"] != null)
                    return (OrderStatus)Enum.Parse(typeof(OrderStatus), ViewState["OrderStatus"].ToString());
                return OrderStatus.Submitted;
            }
        }


 
        protected bool HasNextView()
        {
            return Ids.Count > 0 && Ids.Count > CurrentIndex + 1;
        }
        protected bool HasPreviousView()
        {
            return Ids.Count > 0 && CurrentIndex >= 1;
        }
        protected bool IsLastView
        {
            get
            {
                return CurrentIndex == Ids.Count - 1;
            }

        }
        protected bool IsFirstView
        {
            get
            {
                return CurrentIndex == 0;
            }

        }

        protected virtual bool IsEditable()
        {
            return true;
        }

        protected void SetButtonState(bool isAdd, bool isFirst, bool isLast, bool isSingleEdit, Button btnSave, Button btnCancel, Button btnPrevious, Button btnNext, Button btnSaveAndPrevious, Button btnSaveAndNext, Panel panelBasic)
        {
            btnSave.Visible = btnCancel.Visible = true;
            if (isAdd)
            {
                panelBasic.DefaultButton = btnSave.ID;
                btnPrevious.Visible = btnNext.Visible = btnSaveAndPrevious.Visible = btnSaveAndNext.Visible = false;
            }
            else
            {
                btnSave.Visible = IsEditable();
                if (isSingleEdit)
                {
                    panelBasic.DefaultButton = btnSave.ID;
                    btnPrevious.Visible = btnNext.Visible = btnSaveAndPrevious.Visible = btnSaveAndNext.Visible = false;
                    return;
                }
                btnPrevious.Visible = btnNext.Visible = true;
                btnSaveAndPrevious.Visible = btnSaveAndNext.Visible = btnSave.Visible;
                if (isFirst)
                {
                    panelBasic.DefaultButton = btnSaveAndNext.Visible ? btnSaveAndNext.ID : btnNext.ID;
                    btnPrevious.Enabled = btnSaveAndPrevious.Enabled = false;
                    btnNext.Enabled = btnSaveAndNext.Enabled = true;
                }
                else if (isLast)
                {
                    panelBasic.DefaultButton = btnSaveAndPrevious.Visible ? btnSaveAndPrevious.ID : btnPrevious.ID;
                    btnPrevious.Enabled = btnSaveAndPrevious.Enabled = true;
                    btnNext.Enabled = btnSaveAndNext.Enabled = false;
                }
                else
                {
                    panelBasic.DefaultButton = btnSaveAndNext.Visible ? btnSaveAndNext.ID : btnNext.ID;
                    btnPrevious.Enabled = btnSaveAndPrevious.Enabled = true;
                    btnNext.Enabled = btnSaveAndNext.Enabled = true;
                }

            }

        }


        protected string GetDeliveryAddress(object issuingId)
        {
            if (MiscUtilities.IsNullOrEmpty(issuingId)) return string.Empty;
            var orderService = ServiceContainer.GetService<IIssuingOrderService>();
            var issuingOrderDeliveryData = orderService.GetIssuingOrderDeliveryByOrderId(issuingId.ToString().ToGuid());

            return issuingOrderDeliveryData.Select(a => a.DeliveryAddress).Aggregate((a, b) => a + "," + b);

        }

        protected string GetShortDeliveryAddress(object issuingId)
        {
            var deliveryAddress = GetDeliveryAddress(issuingId);
            if (string.IsNullOrWhiteSpace(deliveryAddress) || deliveryAddress.Length <= 10)
                return deliveryAddress;
            return deliveryAddress.Substring(0, 10) + "...";

        }
    }
}